// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: implementation of CXFormsParseModel.
//   $Id$



#include "stdafx.h"
#include "parseModel.h"
#include "model.h"
#include "parseInstance.h"
#include "implInstance.h"
#include "FP_Definitions.h"
#include "XFormsApp.h"
#include "implBind.h"
#include "parseBind.h"
#include "tags.h"

extern CXFormsApp theApp;
CXFormsParseModel::CXFormsParseModel(CImplModel* pImpl)
		:CXFormsParse( pImpl)
	{
		addAttributeCheck(ATTR_EXTFUNC, &pImpl->m_sExtensionFunctions);
		addAttributeCheck(ATTR_SCHEMA,&pImpl->m_sSchemaURLs);
		addAttributeCheck(ATTR_CONFIG,&pImpl->m_bsConfig);
	};

void CXFormsParseModel::CheckElement(IHTMLElement *pElem, BSTR sTag, CImpl* pImpl)
{
	HRESULT hr = S_OK;

	CImplModel* pModel = (CImplModel*) pImpl;
	if ( TAG_INSTANCE == sTag)
	{
		CImplInstance* pInstance = new CImplInstance(pModel);
		CXFormsParseInstance parse(pInstance);

		hr = parse.Parse(pElem, pInstance);
		if (S_OK == hr)
			hr = pInstance->init(pImpl);

		hr = pModel->addInstance(pInstance->m_sId,pInstance);
		if(FAILED(hr))
			delete pInstance;
	}
	else if (TAG_BIND == sTag)
	{
		CImplBind * pBind = new CImplBind(pModel);
		CXFormsParseBind parse(pBind);
		parse.Parse(pElem, pBind);
		pModel->AddBind(pBind);
	}
	else if (TAG_SCHEMA  == sTag)
	{
		CComVariant vtSchemaId;
		pElem->getAttribute(L"id",0,&vtSchemaId);
		CComBSTR sSchemaId(vtSchemaId.bstrVal);
		VARIANT_BOOL b;
		pElem->removeAttribute(L"id",0,&b);
		CComBSTR sSchemaText;
		pElem->get_outerHTML(&sSchemaText);
		BSTR s = sSchemaText.m_str;
		if(sSchemaText[1]==L'?')
		{
			//IE has added its stupid processing instruction.
			s = &sSchemaText[1];
			while(*s && *s!=L'<')
			{
				++s;
			}
		}
		CComPtr<IXMLDOMDocument> pDoc;
		pImpl->m_pXForms->AddInlineSchema(sSchemaId,s,&pDoc);
		if(pDoc)
		{
			CComPtr<IXMLDOMElement> pElem;
			pDoc->get_documentElement(&pElem);
			if(pElem)
			{
				CComVariant vt;
				pElem->getAttribute(L"targetNamespace",&vt);
				CComBSTR sNSURI;
				if(VT_BSTR == vt.vt)
				{
					sNSURI = vt.bstrVal;
				}
				pDoc->put_resolveExternals(VARIANT_TRUE);
				hr = dynamic_cast<CImplModel*>(pImpl)->m_pSchemaCache->add(sNSURI,CComVariant(pDoc));
				if(FAILED(hr))
				{
					CComPtr<IErrorInfo> pErr;
					::GetErrorInfo(0,&pErr);
					CComBSTR sReason;
					if(pErr)
						pErr->GetDescription(&sReason);
					hr = FP_E_INVALID_SCHEMA;
					theApp.FormsManager().GetErrorSource().SetupErrorInfo(hr,L"inline", vtSchemaId.bstrVal ,sReason);
					pModel->m_pXForms->reportError(hr);
				}
				else
				{
					pModel->m_lstAddedSchemata.push_back(sSchemaId);
				}
			}
		}
	}
}
